近日,比亚迪子公司弗迪电池已在今年3月与特斯拉达成上海储能工厂的供货协议,将于明年一季度向特斯拉供应储能电芯。该工厂的电芯一供已确定为宁德时代,二供为弗迪,后者的供应份额超过20%。
本篇文章来自CoolStew的投稿,文章主要分享了为什么ViewModel可以保存数据,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。https://juejin.cn/user/1627723012245054/posts
ViewModel通过ViewModelProvider类获取,先尝试从ViewModelStore获取ViewModel实例,如果没有,则使用Factory创建,然后存入ViewModelStore。ViewModelStore是ViewModel存储器,内部通过LinkedHashMap存储ViewModel。ViewModelStoreOwner是ViewModel存储器拥有者。ViewModelStoreOwner是个接口,实现类有ComponentActivity和Fragment,也就是说ComponentActivity和Fragment 都是ViewModel存储器的拥有者。屏幕旋转或配置发生变化会调用ComponentActivity的onRetainNonConfigurationInstance方法,在performDestroyActivity阶段执行。Activity对应的ActivityClientRecord变量不受Activity因配置变化而销毁重建的影响。ViewModel如何保存
我们从启动Activity开始,ComponentActivity构造函数中执行ViewModelStore的初始化:
其中getLastNonConfigurationInstance是Activity的方法。可以看出mLastNonConfigurationInstances的赋值发生在Activity.attach方法内,而一开始lastNonConfigurationInstances是没有值的,为null,所以此刻getLastNonConfigurationInstance方法返回的是null,所以ensureViewModelStore方法内会执行:if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}接下来到我们使用ViewModel,有创建两种方式:ViewModelProvider(this).get(XXXViewModel::class.java)
val XXXViewModel: XXXViewModel by viewModel()
不管是哪种,最终都会走到ViewModelProvider的get方法来获取ViewModel。那我们一开始ViewModelStore内肯定是不存在ViewModel的,则使用fatory创建一个,内部使用了反射,然后放入ViewModelStore,内部通过LinkedHashMap存储ViewModel,可以自己看下源码。好了,此时我们的ViewModelStore内部存储了ViewModel实例。接下来我们旋转屏幕,Aactivity1销毁,Aactivity2重建,Aactivity1销毁时,执行到performDestroyActivity时,会执行activity的retainNonConfigurationInstances方法。ComponentActivity重写了这个方法:这个方法很重要,我们一起来看下,这个时候,viewModelStore肯定不为null,所以两个if都不会执行,直接new一个NonConfigurationInstances出来,把当前的viewModelStore赋值给NonConfigurationInstances,其中viewModelStore有我们的viewModel!所以上上图中的activity局部变量是NonConfigurationInstances实例,所以咱们的viewModel一路传递到了performDestroyActivity中的r.lastNonConfigurationInstances中,即ActivityClientRecord中!
我们可以得出结论:我们旋转屏幕,Aactivity1销毁时,会把我们的viewModel保存到ActivityClientRecord中,又因为ActivityClientRecord不受Activity因配置变化而销毁重建的影响,所以它能够帮我们安全得保留了数据。
viewModel如何获取
我们在前面讲到,启动Activity时,ComponentActivity构造函数中执行了ViewModelStore的初始化:此时,getLastNonConfigurationInstance会返回上次在ActivityClientRecord中保留的NonConfigurationInstances实例,里面存储着咱们的viewModelStore以及里面的viewModel,所以nc!=null,ViewModelStore直接被赋值,不会执行下面红框内的new初始化,为什么这次的getLastNonConfigurationInstance方法不是null,因为在Activity.attach方法中,我们对mLastNonConfigurationInstances赋值了,而这次赋值不再是null!推荐阅读:
我的新书,《第一行代码 第3版》已出版!
在Android地图上实现一个雨雪特效吧
原创:写给初学者的Jetpack Compose教程,用derivedStateOf提升性能